package com.jmz.apt.api.service;

import com.jmz.apt.api.Helper.ResponseHelper;
import com.jmz.apt.api.Utils.JsonSerializerUtil;
import com.jmz.apt.api.Utils.MD5Util;
import com.jmz.apt.api.Utils.TokenUtil;
import com.jmz.apt.api.common.AptConstant;
import com.jmz.apt.api.common.SecurityContextHolder;
import com.jmz.apt.api.dto.impl.AdminTokenDto;
import com.jmz.apt.api.entity.dbEntity.JmzAdminRole;
import com.jmz.apt.api.entity.dbEntity.JmzAdminUser;
import com.jmz.apt.api.enums.ResponseCode;
import com.jmz.apt.api.exception.BusinessException;
import com.jmz.apt.api.message.request.RequestMessage;
import com.jmz.apt.api.message.request.RequestMessageTemplate;
import com.jmz.apt.api.message.response.ResponseMessage;
import com.jmz.apt.api.message.response.ResponseMessageTemplate;
import com.jmz.apt.api.service.auth.Login;
import com.jmz.apt.api.service.auth.Token;
import com.jmz.apt.api.service.user.AdminRole;
import com.jmz.apt.api.service.user.AdminUser;
import com.jmz.apt.api.service.user.AdminUserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Created by fanglexue on 2019/11/2.
 */
@Service
public class LoginService {

    @Autowired
    Login login;

    @Autowired
    Token token;

    @Autowired
    AdminUser adminUser;

    @Autowired
    AdminRole adminRole;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    RedisTemplate<String, Serializable> redisTemplate;

    @Autowired
    ResponseMessageTemplate responseMessageTemplate;
    /**
     *
     * @param requestMessage
     * @param response
     * @return
     */
    public ResponseMessage doLogin(RequestMessage requestMessage,ServletResponse response){
        RequestMessageTemplate requestMessageTemplate = new RequestMessageTemplate(requestMessage);
        JmzAdminUser admin = null;
        ResponseHelper responseHelper = new ResponseHelper();
        try{
             admin = login.LoginFindAdminUser(requestMessage);
        }catch (BusinessException be) {
            throw new BusinessException(be.getCode(),be.getMessage());
        }

        if (admin != null) {
            List<AdminTokenDto> adminTokenDtos = token.findAdminUserAsRoleByAdminId(admin.getId());
            AdminTokenDto adminTokenDto = adminTokenDtos.get(0);
            if(adminTokenDto == null){
                responseMessageTemplate.setBussResponse(ResponseCode.LOGIN_FAILURE.getCode(),"未分配权限");
                return responseMessageTemplate.getResponseMessage();
            }
            //Save user permissions in redis
            setAdminPermissions(adminTokenDto.getRoleId());
            //Generates a token and save it in redis
            String newToken = TokenUtil.conferToken(adminTokenDto, AptConstant.TOKEN_EXPIRE);
            setTokenRedis(newToken);
            setTokenRedisMap(newToken,adminTokenDto);

            SecurityContextHolder.addAgent(adminTokenDto);
            System.out.println(SecurityContextHolder.getAgent().getRoleId());
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
            httpServletResponse.setHeader("Cache-Control", "no-store");
            httpServletResponse.setHeader("token", newToken);
            responseHelper.setResponseDataSet("tokenDto",adminTokenDtos);
            responseHelper.setResponseBCode(ResponseCode.SUCCESS.getCode(),ResponseCode.SUCCESS.getDesc());
        } else {
            return responseMessageTemplate.setBussResponse(ResponseCode.LOGIN_FAILURE.getCode(), ResponseCode.LOGIN_FAILURE.getDesc());

        }
        return responseHelper.getResponseMessageTemplate().getResponseMessage();
    }


    public void clearRedisKey(String token,AdminTokenDto adminTokenDto){
        stringRedisTemplate.delete(AptConstant.Redis.TOKEN_INVALID + MD5Util.encode(token));
        redisTemplate.opsForHash().delete(AptConstant.Redis.LOGIN_AGENTS,
                AptConstant.Redis.AGENT_TOKEN + MD5Util.encode(token));
        stringRedisTemplate.delete(AptConstant.Redis.ROLE_PREFIX + adminTokenDto.getRoleId().toString());
        stringRedisTemplate.delete(AptConstant.Redis.TOKEN_REFRESH +  MD5Util.encode(token));
    }


    public void  setAdminPermissions(Integer roleId){
        //Save user permissions in redis
        JmzAdminRole jmzAdminRole = adminRole.findRoleOne(roleId);
        if(null != jmzAdminRole) {
            stringRedisTemplate.opsForValue().set(AptConstant.Redis.ROLE_PREFIX + roleId.toString(),
                    JsonSerializerUtil.obj2String(jmzAdminRole.getResources()));
        }
    }
    public void setTokenRedis(String token){
        stringRedisTemplate.opsForValue().set(AptConstant.Redis.TOKEN_INVALID + MD5Util.encode(token),token);
        stringRedisTemplate.expire(AptConstant.Redis.TOKEN_INVALID + MD5Util.encode(token),30 * 60, TimeUnit.SECONDS);
    }

    public  void  setTokenRedisMap(String token,AdminTokenDto adminTokenDto){
        redisTemplate.opsForHash().put(AptConstant.Redis.LOGIN_AGENTS,
                AptConstant.Redis.AGENT_TOKEN + MD5Util.encode(token), adminTokenDto);
    }

    public void setRefreshToken(String newToken, String token){
        Long oldExpire = stringRedisTemplate.getExpire(AptConstant.Redis.TOKEN_REFRESH + MD5Util.encode(token), TimeUnit.SECONDS);
        stringRedisTemplate.opsForValue().set(AptConstant.Redis.TOKEN_REFRESH + MD5Util.encode(newToken), UUID.randomUUID().toString());
        stringRedisTemplate.expire(AptConstant.Redis.TOKEN_REFRESH +  MD5Util.encode(newToken), oldExpire, TimeUnit.SECONDS);
        stringRedisTemplate.delete(AptConstant.Redis.TOKEN_REFRESH +  MD5Util.encode(token));
    }

    public void  setTokenBackList(String newToken, String token){
        stringRedisTemplate.opsForValue().set(AptConstant.Redis.TOKEN_BLACKLIST + MD5Util.encode(token), newToken);
        stringRedisTemplate.expire(AptConstant.Redis.TOKEN_BLACKLIST + MD5Util.encode(token), 30, TimeUnit.SECONDS);
        redisTemplate.opsForHash().delete(AptConstant.Redis.LOGIN_AGENTS,
                AptConstant.Redis.AGENT_TOKEN + MD5Util.encode(token));
    }

    /**
     *
     * @param response
     * @return
     */
    //public ResponseMessage logOut(ServletResponse response);
}
